/*
 * CCVisu is a tool for visual graph clustering
 * and general force-directed graph layout.
 * This file is part of CCVisu.
 *
 * Copyright (C) 2005-2012  Dirk Beyer
 *
 * CCVisu is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * CCVisu is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with CCVisu; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Please find the GNU Lesser General Public License in file
 * license_lgpl.txt or http://www.gnu.org/licenses/lgpl.txt
 *
 * Dirk Beyer    (firstname.lastname@uni-passau.de)
 * University of Passau, Bavaria, Germany
 */
package org.sosy_lab.ccvisu.readers.factextractor;

import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.IPackageBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;

import com.google.common.base.Strings;

public class FactUtils {

  /** The name of the package of a class, if no package is given. */
  public final static String DEFAULT_PACKAGE_NAME = "(default)";

  public static String getMethodFullName(MethodDeclaration md) {
    assert md != null;

    StringBuilder result = new StringBuilder();

    if (md.getParent() instanceof TypeDeclaration) {
      TypeDeclaration typeDeclaration = (TypeDeclaration) md.getParent();
      ITypeBinding typeBinding = typeDeclaration.resolveBinding();
      IPackageBinding packageBinding = typeBinding.getPackage();

      result.append(FactUtils.getPackageName(packageBinding));
      result.append('.');
      result.append(typeDeclaration.getName().getFullyQualifiedName());
      result.append('.');
    }

    result.append(md.getName().getFullyQualifiedName()).append("()");
    return result.toString();
  }

  public static String getTypeFullName(MethodDeclaration md) {
    assert md != null;

    StringBuffer result = new StringBuffer();

    if (md.getParent() instanceof TypeDeclaration) {
      TypeDeclaration typeDeclaration = (TypeDeclaration) md.getParent();
      ITypeBinding typeBinding = typeDeclaration.resolveBinding();
      IPackageBinding packageBinding = typeBinding.getPackage();

      result.append(FactUtils.getPackageName(packageBinding));
      result.append('.');
      result.append(typeDeclaration.getName().getFullyQualifiedName());
    }

    return result.toString();
  }

  public static String getTypeFullName(ITypeBinding typeBinding) {
    if (typeBinding == null) { return null; }

    StringBuffer result = new StringBuffer();

    IPackageBinding packageBinding = typeBinding.getPackage();

    result.append(FactUtils.getPackageName(packageBinding));
    result.append('.');
    result.append(typeBinding.getName());

    return result.toString();
  }

  public static String getTypeFullName(TypeDeclaration type) {
    String result = null;

    ITypeBinding typeBinding = type.resolveBinding();
    IPackageBinding packageBinding = typeBinding.getPackage();

    result = FactUtils.getPackageName(packageBinding) + "."
        + typeBinding.getName();

    return result;
  }

  public static String getEnumFullName(EnumDeclaration pEnum) {
    String result = null;

    ITypeBinding typeBinding = pEnum.resolveBinding();
    IPackageBinding packageBinding = typeBinding.getPackage();

    result = FactUtils.getPackageName(packageBinding) + "."
        + typeBinding.getName();

    return result;
  }

  public static String getTypeFullName(Type type) {
    if (type == null) { return null; }

    ITypeBinding typeBinding = type.resolveBinding();
    if (typeBinding == null) { return null; }
    IPackageBinding packageBinding = typeBinding.getPackage();

    String result = FactUtils.getPackageName(packageBinding) + "."
        + typeBinding.getName();

    return result;
  }

  public static String getTypeFullName(MethodInvocation mi) {
    String result = null;

    IMethodBinding methodBinding = mi.resolveMethodBinding();
    if (methodBinding != null) {
      ITypeBinding typeBinding = methodBinding.getDeclaringClass();
      IPackageBinding packageBinding = typeBinding.getPackage();

      result = FactUtils.getPackageName(packageBinding) + "."
          + typeBinding.getName();
    }

    return result;
  }

  private static String getPackageName(IPackageBinding packageBinding) {
    String result = packageBinding.getName();
    if (Strings.isNullOrEmpty(result)) {
      result = FactUtils.DEFAULT_PACKAGE_NAME;
    }

    return result;
  }

  public static String getPackageName(ITypeBinding typeBinding) {
    IPackageBinding packageBinding = typeBinding.getPackage();

    return FactUtils.getPackageName(packageBinding);
  }

  public static String getPackageName(MethodDeclaration md) {
    String result = null;

    IMethodBinding methodBinding = md.resolveBinding();
    if (methodBinding != null) {
      ITypeBinding typeBinding = methodBinding.getDeclaringClass();
      IPackageBinding packageBinding = typeBinding.getPackage();

      result = FactUtils.getPackageName(packageBinding);
    }

    return result;
  }

  public static String getPackageName(EnumDeclaration node) {
    String result = null;

    ITypeBinding typeBinding = node.resolveBinding();
    if (typeBinding != null) {
      IPackageBinding packageBinding = typeBinding.getPackage();

      result = FactUtils.getPackageName(packageBinding);
    }

    return result;
  }

  public static String getMethodFullName(MethodInvocation mi) {
    String result = null;

    IMethodBinding methodBinding = mi.resolveMethodBinding();

    if (methodBinding != null) {
      ITypeBinding typeBinding = methodBinding.getDeclaringClass();
      IPackageBinding packageBinding = typeBinding.getPackage();

      result = FactUtils.getPackageName(packageBinding) + "."
          + typeBinding.getName() + "." + methodBinding.getName() + "()";
    }

    return result;
  }

  public static String getPackageName(MethodInvocation mi) {
    String result = null;

    IMethodBinding methodBinding = mi.resolveMethodBinding();
    if (methodBinding != null) {
      ITypeBinding typeBinding = methodBinding.getDeclaringClass();
      IPackageBinding packageBinding = typeBinding.getPackage();

      result = packageBinding.getName();
      if (Strings.isNullOrEmpty(result)) {
        result = FactUtils.DEFAULT_PACKAGE_NAME;
      }
    }

    return result;
  }

  public static String getPackageName(TypeDeclaration type) {
    String result = null;

    ITypeBinding typeBinding = type.resolveBinding();
    IPackageBinding packageBinding = typeBinding.getPackage();

    result = packageBinding.getName();
    if (Strings.isNullOrEmpty(result)) {
      result = FactUtils.DEFAULT_PACKAGE_NAME;
    }

    return result;
  }

  public static String getPackageName(PackageDeclaration pckg) {
    String result = null;

    result = pckg.getName().getFullyQualifiedName();
    if (Strings.isNullOrEmpty(result)) {
      result = FactUtils.DEFAULT_PACKAGE_NAME;
    }

    return result;
  }

  public static String getPackageName(Type superclassType) {
    String result = null;

    if (superclassType == null) { return null; }

    ITypeBinding typeBinding = superclassType.resolveBinding();
    if (typeBinding == null) { return null; }

    IPackageBinding packageBinding = typeBinding.getPackage();

    result = packageBinding.getName();
    if (Strings.isNullOrEmpty(result)) {
      result = FactUtils.DEFAULT_PACKAGE_NAME;
    }

    return result;
  }
}
